import zipfile
import os
import time
import threading
import shutil
import json
import traceback
import hashlib
import subprocess

from flask import Flask
from flask import request


UPLOAD_FOLDER = os.getcwd()
CURRENT_CHUNK = 0

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

def get_md5(path):
    m = hashlib.md5()
    with open(path, 'rb') as f:
        for line in f:
            m.update(line)
    md5code = m.hexdigest()
    return md5code

@app.route("/", methods=['GET', 'POST'])
def hello_world():
    return "Hello, World!"

@app.route("/new_pack", methods=['POST'])
def get_new_game_package():
    global CURRENT_CHUNK
    try:
        print("On New Game Package, args: {}".format(request.form))
        filename = request.form.get('filename', '')
        f = request.files['file']
        current_chunk = request.form.get('currentChunk')
        total_chunk = request.form.get('totalChunk')
        print(total_chunk, current_chunk)
        if current_chunk is None or total_chunk is None:
            msg = "current_chunk is None or total_chunk is None!"
            print(msg)
            return msg, 400
        current_chunk = int(current_chunk)
        total_chunk = int(total_chunk)
        if current_chunk == 1:
            if os.path.exists(filename + ".zip"):
                os.remove(filename + ".zip")
        elif CURRENT_CHUNK == current_chunk:
            msg = "Chunk {} has been sent".format(current_chunk)
            print(msg)
            return msg, 200
        with open(filename + ".zip", "ab") as wf:
            wf.write(f.read())
        if current_chunk == total_chunk:
            md5 = get_md5(filename + ".zip")
            if md5 != request.form.get('md5'):
                msg = "MD5 mismatch {} vs {}".format(md5, request.form.get('md5'))
                print(msg)
                return msg, 401
            zip = zipfile.ZipFile(filename + ".zip", "r")
            zip.extractall(filename)
            final_path = os.path.join(os.getcwd(), filename)
            print("unzip Finish, result dir is {}".format(final_path))
        CURRENT_CHUNK = current_chunk
        return "OK", 200
    except:
        traceback.print_exc()
        return "Server Error", 500

@app.route("/start_game", methods=['POST'])
def start_game():
    try:
        print("On start_game, args: {}".format(request.form))
        pack_name = request.form.get('pack_name')
        cmds = json.loads(request.form.get('cmds'))
        outputs = exec_cmds(pack_name, cmds)
        return json.dumps(outputs), 200
    except:
        traceback.print_exc()
        return "Server Error", 500

@app.route("/kill_game", methods=['POST'])
def kill_game():
    try:
        print("On Kill game")
        os.system("kill_game.bat")
        return "OK", 200
    except:
        traceback.print_exc()
        return "Server Error", 500

@app.route("/restart_game", methods=['POST'])
def restart_game():
    try:
        print("On Restart game, args: {}".format(request.form))
        kill_game()
        start_game()
        return "OK", 200
    except:
        traceback.print_exc()
        return "Server Error", 500

def exec_cmds(dir, cmds):
    old_cwd = os.getcwd()
    try:
        target_dir = os.path.join(old_cwd, dir)
        print("cd " + target_dir)
        os.chdir(target_dir)
        outputs = []
        for bat in cmds:
            print(bat)
            process = subprocess.Popen(bat, stdout=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
            try:
                stdout, stderr = process.communicate(timeout=10)
                outputs.append(stdout.decode('gbk'))
            except Exception as e:
                continue

            # os.system(bat)
            # time.sleep(10)
        return outputs
    except:
        traceback.print_exc()
    finally:
        os.chdir(old_cwd)


if __name__ == "__main__":
    app.run(host='0.0.0.0',port=50000)
